package com.zhl.study.service.impl;

import com.alibaba.fastjson.JSONArray;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.zhl.study.configuration.Mineral;
import com.zhl.study.configuration.MineralLevelMock;
import com.zhl.study.configuration.PlayerMineral;
import com.zhl.study.service.IMineralService;
import com.zhl.study.service.IPlayerMineralService;
import com.zhl.study.mapper.PlayerMineralMapper;
import com.zhl.study.util.CalculateKit;
import lombok.AllArgsConstructor;
import org.springframework.stereotype.Service;

import java.math.BigDecimal;
import java.util.*;
import java.util.stream.Collectors;

@Service
@AllArgsConstructor
public class PlayerMineralServiceImpl extends ServiceImpl<PlayerMineralMapper, PlayerMineral> implements IPlayerMineralService {

    private final IMineralService mineralService;

    @Override
    public void createDefaultMineral(int playerId) {
        List<Mineral> minerals = mineralService.lambdaQuery().eq(Mineral::getStatus, 1).list();
        // TODO 矿产数据不能为空
        List<PlayerMineral> playerMinerals = minerals
                .stream()
                .map(mineral -> PlayerMineral.builder()
                        .level(BigDecimal.ZERO.intValue())
                        .playerId(playerId)
                        .no(mineral.getNo())
                        .name(mineral.getName())
                        .introduce(mineral.getIntroduce())
                        .icon(mineral.getIcon())
                        .phase(BigDecimal.ONE.intValue())
                        .startLevel(BigDecimal.ZERO.intValue())
                        .endLevel(Integer.parseInt(mineral.getRankUpRule().split(",")[0]))
                        .earningsCnt(BigDecimal.ZERO)
                        .earningsSingleCnt(BigDecimal.ZERO)
//                        .earningsFrequenc(BigDecimal.ZERO)
                        .nextTime(BigDecimal.ZERO.longValue())
                        .activate(BigDecimal.ZERO.intValue())
                        .createTime(System.currentTimeMillis())
                        .resetTimes(BigDecimal.ZERO.intValue())
                        .build())
                .collect(Collectors.toList());
        this.saveBatch(playerMinerals);
    }

    @Override
    public void activationMineral(int mineralNo, int playerId) {
        Mineral mineral = mineralService.lambdaQuery().eq(Mineral::getStatus, 1).eq(Mineral::getNo, mineralNo).one();
        // TODO 矿产不能为空
        PlayerMineral playerMineral = this.lambdaQuery().eq(PlayerMineral::getActivate, 0).eq(PlayerMineral::getPlayerId, playerId).eq(PlayerMineral::getNo, mineralNo).one();
        // TODO 玩家矿产是否存在
        BigDecimal unlockCost = mineral.getUnlockCost();
        // TODO 查询玩家当前基础货币的余额（需要实时计算一下），是否满足当前激活解锁的要求，假设当前满足
        // TODO 减去当前消耗，重置基础货币余额
        // 更新玩家矿产基础信息
        this.lambdaUpdate().set(PlayerMineral::getActivate, 1).eq(PlayerMineral::getId, playerMineral.getId()).update();
    }

    @Override
    public void upgrades(long playerMineralId, int currentLevel, int level) {
        PlayerMineral playerMineral = this.getById(playerMineralId);
        // TODO 判断玩家矿产数据是否存在，是否激活,等级是否正常
        /**这部分代码是获取玩家每一级的数据，后期考虑做到 redis 中*/
        // TODO 获取这条矿产的成长配置数据
        Mineral mineral = mineralService.lambdaQuery().eq(Mineral::getNo, playerMineral.getNo()).eq(Mineral::getStatus, 1).one();
        // TODO 判断矿产数据是否存在
        for (int i = level; i > 0; i--) {
            // 等级的BigDecimal类型
            BigDecimal levelDecimal = CalculateKit.getBigDecimal(currentLevel);
            // 计算基础成长消耗
            Map<String, BigDecimal> escalationCostParamMap = new HashMap<>();
            escalationCostParamMap.put("a", CalculateKit.divideOneThousandKeepThree(mineral.getCostA()));
            escalationCostParamMap.put("b", CalculateKit.divideOneThousandKeepThree(mineral.getCostB()));
            escalationCostParamMap.put("c", CalculateKit.divideOneThousandKeepThree(mineral.getCostC()));
            escalationCostParamMap.put("d", CalculateKit.divideOneThousandKeepThree(mineral.getCostD()));
            escalationCostParamMap.put("e", CalculateKit.divideOneThousandKeepThree(mineral.getCostE()));
            escalationCostParamMap.put("x", levelDecimal);
            BigDecimal escalationCosNum = CalculateKit.calculateFormula(mineral.getEscalationCostFormula(), escalationCostParamMap);

            // 计算当前等级基础产出（不算等阶加成）
            Map<String, BigDecimal> outputParamMap = new HashMap<>();
            outputParamMap.put("x", levelDecimal);
            outputParamMap.put("a", CalculateKit.divideOneThousandKeepThree(mineral.getOutputA()));
            outputParamMap.put("b", CalculateKit.divideOneThousandKeepThree(mineral.getOutputB()));
            BigDecimal outputNum = CalculateKit.calculateFormula(mineral.getOutputFormula(), outputParamMap);

            // 计算当前等级的产出cd时间（不算等阶加成）
            BigDecimal cdTime = mineral.getInitialFrequency();

            // 计算当前等阶，如果超过当前等阶需要升阶
            int rankUpChange = mineral.getRankUpChange();
            int phase = playerMineral.getPhase();
            currentLevel++;
            if (currentLevel > playerMineral.getEndLevel()) {
                String rankUpRule = mineral.getRankUpRule();
                String[] rankUpRuleArrays = rankUpRule.split(",");
                int addLevel = 0;
                if (phase >= rankUpRuleArrays.length){
                    addLevel = Integer.parseInt(rankUpRuleArrays[rankUpRuleArrays.length-1]);
                } else {
                    addLevel = Integer.parseInt(rankUpRuleArrays[phase]);
                }
                phase++;
                playerMineral.setPhase(phase);
                playerMineral.setStartLevel(playerMineral.getEndLevel() + 1);
                playerMineral.setEndLevel(playerMineral.getEndLevel() + addLevel);
            }
            // 当前等阶是缩短cd还是加产出?


        }
        /**这部分代码是获取玩家每一级的数据，后期考虑做到 redis 中*/
    }

    @Override
    public void generateThousandthGradeJson() {
        List<Mineral> mineralList = mineralService.lambdaQuery().eq(Mineral::getStatus, 1).list();
        // TODO 矿产数据不能为空
        int maxPhase = 20;
        List<MineralLevelMock> mineralLevelList = new ArrayList<>();
        for (Mineral mineral : mineralList) {
            // 计算等阶
            String rankUpRule = mineral.getRankUpRule();
            String[] rankUpRuleArrays = rankUpRule.split(",");

            List<Integer> phaseLevel = new ArrayList<>(maxPhase);
            int lastPhaseStartLevel = 0;
            for (int i = 0; i <= maxPhase; i++) {
                if (i < rankUpRuleArrays.length && i > 0) {
                    lastPhaseStartLevel += Integer.parseInt(rankUpRuleArrays[i-1]);
                }
                if (i >= rankUpRuleArrays.length) {
                    lastPhaseStartLevel += Integer.parseInt(rankUpRuleArrays[rankUpRuleArrays.length-1]);
                }
                phaseLevel.add(lastPhaseStartLevel);
            }
            // 等级
            int level = 0;

            // 当前等级升级消耗基础货币
            Map<String, BigDecimal> escalationCostParamMap = new HashMap<>();
            escalationCostParamMap.put("a", CalculateKit.divideOneThousandKeepThree(mineral.getCostA()));
            escalationCostParamMap.put("b", CalculateKit.divideOneThousandKeepThree(mineral.getCostB()));
            escalationCostParamMap.put("c", CalculateKit.divideOneThousandKeepThree(mineral.getCostC()));
            escalationCostParamMap.put("d", CalculateKit.divideOneThousandKeepThree(mineral.getCostD()));
            escalationCostParamMap.put("e", CalculateKit.divideOneThousandKeepThree(mineral.getCostE()));

            // 计算当前等级基础产出（不算等阶加成）
            Map<String, BigDecimal> outputParamMap = new HashMap<>();
            outputParamMap.put("a", CalculateKit.divideOneThousandKeepThree(mineral.getOutputA()));
            outputParamMap.put("b", CalculateKit.divideOneThousandKeepThree(mineral.getOutputB()));

            // 等阶加成的收入加成计算
            Map<String, BigDecimal> summaryOutputParamMap = new HashMap<>();
            summaryOutputParamMap.put("c", CalculateKit.divideOneThousandKeepThree(mineral.getRankUpOutputMultiple()));

            // 基础 cd
            BigDecimal initialFrequency = CalculateKit.divideOneThousandKeepThree(mineral.getInitialFrequency());
            BigDecimal rankUpCdShortenMultiple = CalculateKit.divideOneThousandKeepThree(mineral.getRankUpCdShortenMultiple());
            // 计算当前等级基础产出（不算等阶加成）
            Map<String, BigDecimal> frequencyParamMap = new HashMap<>();
            frequencyParamMap.put("a", initialFrequency);
            frequencyParamMap.put("b", rankUpCdShortenMultiple);

            // 编号
            int no = mineral.getNo();
            // 等阶
            int phase = 0;
            // 当前等阶开始等级(默认第一阶段)
            int startLevel = phaseLevel.get(0);
            // 当前等阶结束等级(默认第一阶段)
            int endLevel = phaseLevel.get(1);
            while (true){
                BigDecimal levelDecimal = CalculateKit.getBigDecimal(level);
                for (int i = 0; i < phaseLevel.size(); i++) {
                    if (level == endLevel) {
                        // 升阶
                        phase++;
                        startLevel = phaseLevel.get(i + 1);
                        endLevel = phaseLevel.get(i + 2);
                    }
                    break;
                }

                // 当前等级升级消耗基础货币(这个是没有道具影响的基础消耗数量)
                escalationCostParamMap.put("x", levelDecimal);
                BigDecimal upgradeCost = CalculateKit.calculateFormula(mineral.getEscalationCostFormula(), escalationCostParamMap);

                // 计算当前等级基础产出（不算等阶加成）
                outputParamMap.put("x", levelDecimal);
                BigDecimal earningsSingleCnt = CalculateKit.calculateFormula(mineral.getOutputFormula(), outputParamMap);

                // 出售矿产获取钻石数量计算


                // 当前产出频率（单位秒）
                BigDecimal earningsFrequency = initialFrequency;
                // 计算当前等阶，如果超过当前等阶需要升阶
                int rankUpChange = mineral.getRankUpChange();
                // 如果当前等阶小于等于当前的升阶变化数则当前这一阶都减 cd
                BigDecimal rankUpChangeDecimal = CalculateKit.getBigDecimal(rankUpChange);
                BigDecimal phaseDecimal = CalculateKit.getBigDecimal(phase);
                if (rankUpChange > 0 && phase > 0){
                    // 等阶变化数和等阶都大于 0 不管哪一阶都要计算 cd
                    frequencyParamMap.put("x", phaseDecimal);
                    if (phase > rankUpChange){
                        frequencyParamMap.put("x", rankUpChangeDecimal);
                    }
                    // 减 cd 计算
                    earningsFrequency = CalculateKit.calculateFormula(mineral.getFrequencyFormula(), frequencyParamMap);
                }

                // 超过等阶变化数增加收入，在基础收益上增加倍数
                BigDecimal earningsPhase = BigDecimal.ZERO;
                if (phase > rankUpChange){
                    summaryOutputParamMap.put("a", earningsSingleCnt);
                    summaryOutputParamMap.put("b", rankUpChangeDecimal);
                    summaryOutputParamMap.put("x", levelDecimal);
                    earningsPhase = CalculateKit.calculateFormula(mineral.getSummaryOutputFormula(), summaryOutputParamMap);
                }
                MineralLevelMock mineralLevelMock = MineralLevelMock
                        .builder()
                        .level(level)
                        .no(no)
                        .phase(phase)
                        .startLevel(startLevel)
                        .endLevel(endLevel)
                        .upgradeCost(upgradeCost)
                        .earningsSingleCnt(earningsSingleCnt)
                        .earningsFrequency(earningsFrequency)
                        .earningsPhase(earningsPhase)
                        .build();
                mineralLevelList.add(mineralLevelMock);
                level++;
                if (level > phaseLevel.get(phaseLevel.size() -1)){
                    break;
                }
            }
        }
        System.out.println(JSONArray.toJSONString(mineralLevelList));
    }
}
